<?php
/*
* Copyright (c) 2010 by Cediti
*
* You may distribute under the terms of either the GNU Lesser General
* Public License or the new BSD License, as specified in the README file.
*/
// created :    09/02/2010
// version :    22/04/2010

class Cmis_Client_Services_Generic_Object extends Cmis_Services_Abstract implements Cmis_Services_Object
{
	/**
	 * @var array[Cmis_Repository_Entry]
	 */
	protected $_lastEntry;

	public function createDocument(Cmis_Repository_Id $repositoryId, Cmis_Repository_Properties $properties, Cmis_Repository_Id $folderId = null, array $contentStream = null, $versioningState = 'major', array $policies = null, array $addACEs = null, array $removeACEs = null)
	{
		//check repository
		$cur = $this->_getRepositoryInfo($repositoryId);

		if (empty($folderId) || $folderId->isEmpty())
		{
			if (!$cur->getCapabilities('Unfiling'))
			{
				throw new Cmis_Exception_Services_NoCapability('unfiling');
			}
		}
		else
		{
			$folder = $this->getAllowableActions($repositoryId, $folderId);;

			if(!$folder->get('canCreateDocument'))
			{
				throw new Cmis_Exception_Document_CantCreate('Can\'t create document in this folder!');
			}
		}

		//check properties
		$date = date(DATE_ATOM, time());

		if (!$properties->get('cmis:LastModificationDate'))
		{
			$properties->set('cmis:LastModificationDate', Cmis_Repository_Properties::TYPE_DATE, $date);
		}

		if (!$properties->get('cmis:creationDate'))
		{
			$properties->set('cmis:creationDate', Cmis_Repository_Properties::TYPE_DATE, $date);
		}

		if (!$properties->get('cmis:objectTypeId'))
		{
			$properties->set('cmis:objectTypeId', Cmis_Repository_Properties::TYPE_ID, 'cmis:document');
		}

		if (!$properties->get('cmis:contentStreamFileName'))
		{
			$properties->set('cmis:contentStreamFileName', Cmis_Repository_Properties::TYPE_STRING, $properties->get('cmis:name'));
		}
		elseif (!$properties->get('cmis:name'))
		{
			$properties->set('cmis:name', Cmis_Repository_Properties::TYPE_STRING, $properties->get('cmis:contentStreamFileName'));
		}

		$num = func_num_args();
		$title = ($num > 8)?func_get_arg(8):$properties->get('cmis:name');
		$summary = ($num > 9)?func_get_arg(9):$properties->get('cmis:name');

		//create xml file
		$tpl = new Cmis_XmlTemplates();
		$tpl->addFile('post/new_entry.xml.tpl', 'entry')
		->addFile('content.xml.tpl', 'content')
		->setVar('content', $tpl->render('content'), 'entry');

		$tpl->setVar('properties', $properties->render(), 'entry')
		->setVar('update', (string)$properties->get('cmis:LastModificationDate'), 'entry')
		->setVar('title', $title, 'entry')
		->setVar('summary', $summary, 'entry')
		->setSubVar('mimetype', 'content', $contentStream[0], 'entry')
		->setSubVar('value', 'content', $contentStream[1], 'entry')
		->setSubVar('encoding', 'content', 'base64', 'entry');
		$contentStream[2] = $tpl->createFromBlocks('entry');

		try
		{
			//        	Debug::active();
			/* @var $response Cmis_Http_Response */
			$response = $this->getServices()->getProtocolService('Object')->createDocument($repositoryId, $properties, $folderId, $contentStream, $versioningState, $policies, $addACEs, $removeACEs);
			//        	Debug::var_debug($this->getServices()->getProtocolService('Object')->getProtocolClient());
			//        	exit();
		}
		catch(Cmis_Exception_Request_BadHTTPCode $e)
		{
			switch ($e->getCode())
			{
				case 201 :
					//ok -> created
					break;
				case 500 :
					//duplicata
					throw new Cmis_Exception_Document_AlreadyExist($e);
				default :
					throw new Cmis_Exception_Services_Services($e);
			}
		}

		if (empty($response))
		{
			return null;
		}

		return new Cmis_Repository_Entry($response->toXml(), $repositoryId);
	}

	public function createFolder(Cmis_Repository_Id $repositoryId, Cmis_Repository_Properties $properties, Cmis_Repository_Id $folderId, array $policies = null, array $addACEs = null, array $removeACEs = null)
	{
		$cur = $this->_getRepositoryInfo($repositoryId);

		//can we create a folder?
		$folder = $this->getAllowableActions($repositoryId, $folderId);

		if(!$folder->get('canCreateFolder'))
		{
			throw new Cmis_Exception_Folder_CantCreate('Can\'t create folder in this folder!');
		}

		//check properties
		$date = date(DATE_ATOM, time());

		if (!$properties->get('cmis:LastModificationDate'))
		{
			$properties->set('cmis:LastModificationDate', Cmis_Repository_Properties::TYPE_DATE, $date);
		}

		if (!$properties->get('cmis:creationDate'))
		{
			$properties->set('cmis:creationDate', Cmis_Repository_Properties::TYPE_DATE, $date);
		}

		if (!$properties->get('cmis:objectTypeId'))
		{
			$properties->set('cmis:objectTypeId', Cmis_Repository_Properties::TYPE_ID, 'cmis:folder');
		}

		//create templates
		//create xml file
		$tpl = new Cmis_XmlTemplates();
		$tpl->addFile('post/new_entry.xml.tpl', 'entry');

		$num = func_num_args();
		$title = ($num >= 6)?func_get_arg(6):$properties->get('cmis:name');
		$summary = ($num >= 7)?func_get_arg(7):$properties->get('cmis:name');

		$tpl->setVar('properties', $properties->render(), 'entry')
		->setVar('update', (string)$properties->get('cmis:LastModificationDate'), 'entry')
		->setVar('title', $title, 'entry')
		->setVar('summary', $summary, 'entry')
		->setVar('content', '', 'entry');

		try
		{
			$response = $this->getServices()->getProtocolService('Object')->createFolder($repositoryId, $properties, $folderId, $policies, $addACEs, $removeACEs, $tpl->createFromBlocks('entry'));
		}
		catch(Cmis_Exception_Request_BadHTTPCode $e)
		{
			switch ($e->getCode())
			{
				case 201 :
					//ok
					break;
                case 500 :
                    //duplicata
                    throw new Cmis_Exception_Folder_AlreadyExist($e);
				default :
					throw new Cmis_Exception_Services_Services($e);
			}
		}

		if (empty($response))
		{
			return null;
		}

		return new Cmis_Repository_Entry($response->toXml(), $repositoryId);
	}

	public function createRelationship(Cmis_Repository_Id $repositoryId, $typeId, $properties, $sourceObjectId, $targetObjectId)
	{
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function createPolicy(Cmis_Repository_Id $repositoryId, $typeId, $properties, $folderId)
	{
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function getAllowableActions(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId)
	{
		$object = $this->getObject($repositoryId, $objectId, null, null, false, null, false, true);
		$allowableActions = $object->getAllowableActions();
		if (empty($allowableActions) || count($allowableActions) < 1)
		{
			$response = $this->getServices()->getProtocolService('Object')->getAllowableActions($repositoryId, $objectId);
			$allowableActions = new Cmis_Repository_AllowableActions();
			$allowableActions->setXmlResponse($response->toXml());
		}
		return $allowableActions;
	}

	/*http://docs.oasis-open.org/cmis/CMIS/v1.0/cs01/cmis-spec-v1.0.html#_Toc243905392*/
	public function getProperties(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $filter = null)
	{
		$object = $this->getObject($repositoryId, $objectId, $filter);
		return $object->getProperties();
	}

	public function getContentStream(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $streamId = null)
	{
		return $this->getServices()->getProtocolService('Object')->getContentStream($repositoryId, $objectId, $streamId);
	}

	public function updateProperties(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $changeToken, $propertyCollection)
	{
		//Changes
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function moveObject(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $targetFolderId, $sourceFolderId)
	{
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function deleteObject(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $allVersions = true)
	{
		$allowable = $this->getAllowableActions($repositoryId, $objectId);

		if (!$allowable->get('cmis:canDeleteObject'))
		{
			throw new Cmis_Exception_Object_CantDelete('Object can\'t be deleted');
		}

		try
		{
			$this->getServices()->getProtocolService('Object')->deleteObject($repositoryId, $objectId, $allVersions);
		}
		catch(Cmis_Exception_Request_BadHTTPCode $e)
		{
			switch ($e->getCode())
			{
				case 204 :
					break;
				default :
					throw new Cmis_Exception_Services_Services($e);
			}
		}
	}

	public function deteleTree(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $folderId, $unfileNonfolderObjects)
	{
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function setContentStream(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $overwriteFlag, $content, $properties)
	{
		/*$cur = $this->_getRepositoryInfo($repositoryId);
		 switch($cur->getCapapbilities('ContentStreamUpdatability'))
		 {
		 case Cmis_Repository_Capability_ContentStreamUpdatability::VALUE_NONE :
		 throw new Cmis_Exception_Services_NoCapability('create');
		 case Cmis_Repository_Capability_ContentStreamUpdatability::VALUE_ANYTIME :
		 case Cmis_Repository_Capability_ContentStreamUpdatability::VALUE_PWCONLY :
		 }*/
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function deleteContentStream(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId)
	{
		die('-[Must be implemented : ' . __METHOD__ . ' (' . __FILE__ . '#' . __LINE__ . ')]-');
	}

	public function getObject(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, $filter = null, $includeRelationships = null, $includePolicyIds = false, $renditionFilter = null, $includeACL = false, $includeAllowableActions = false)
	{
		//Renditions
		$last = $this->_getLastEntry($repositoryId, $objectId);

		if (is_null($last))
		{
			$response = $this->getServices()->getProtocolService('Object')->getObject($repositoryId, $objectId, $filter, $includeRelationships, $includePolicyIds, $renditionFilter, $includeACL, $includeAllowableActions);

			if (empty($response))
			{
				return null;
			}

			$last = new Cmis_Repository_Entry($response->toXml(), $repositoryId);

			$this->_setLastEntry($repositoryId, $last->getObjectId(), $last);
		}
		elseif($includeAllowableActions && count($last->getAllowableActions()) == 0)
		{
			unset($this->_lastEntry[ $this->_cmisId2Id($repositoryId, $objectId) ]);
			return $this->getObject($repositoryId, $objectId, $filter, $includeRelationships, $includePolicyIds, $renditionFilter, $includeACL, $includeAllowableActions);
		}

		return $last;
	}

	public function getObjectByPath(Cmis_Repository_Id $repositoryId, $path, $filter = null, $includeAllowableActions = false, $includeRelationships = null, $renditionFilter = null, $includePolicyIds = false, $includeACL = false)
	{
		$response = $this->getServices()->getProtocolService('Object')->getObjectByPath($repositoryId, $path, $filter, $includeAllowableActions, $includeRelationships, $renditionFilter, $includePolicyIds, $includeACL);

		if (empty($response))
		{
			return null;
		}

		$entry = new Cmis_Repository_Entry($response->toXml(), $repositoryId);

		$this->_setLastEntry($repositoryId, $entry->getObjectId(), $entry);

		return $entry;
	}

	/**
	 * Get an entry already reach
	 * @param Cmis_Repository_Id $repositoryId
	 * @param Cmis_Repository_Id $objectId
	 * @return Cmis_Repository_Entry
	 */
	protected function _getLastEntry(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId)
	{
		$id = $this->_cmisId2Id($repositoryId, $objectId);
		return (!is_null($this->_lastEntry) && isset($this->_lastEntry[ $id ]))? $this->_lastEntry[ $id ] : null;
	}

	/**
	 * Define the entry
	 * @param Cmis_Repository_Id $repositoryId
	 * @param Cmis_Repository_Id $objectId
	 * @param Cmis_Repository_Entry $entry
	 * @return void
	 */
	protected function _setLastEntry(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId, Cmis_Repository_Entry $entry)
	{
		$this->_lastEntry[ $this->_cmisId2Id($repositoryId, $objectId) ] = $entry;
	}

	/**
	 * Make a id for storage from the 2 id given
	 * @param Cmis_Repository_Id $repositoryId
	 * @param Cmis_Repository_Id $objectId
	 * @return string
	 */
	protected function _cmisId2Id(Cmis_Repository_Id $repositoryId, Cmis_Repository_Id $objectId)
	{
		return $repositoryId->getId() . $objectId->getId();
	}
}

# EOF
